import { $toast } from "@/components/toast";
import xhr from "@/utils/http";
import { CancelToken } from 'axios'

const MESSAGE = {
  REQ_LOCATION: 1,
  RES_LOCATION: 2,
  RESET: 0
}

const TYPE = {
  SEND: 'send',
  RECEIVE: 'receive',
}

const content = {
  message: '',
  lngLat: '',
  requestTimeStr: '',
  responseTimeStr: '',
}

let cancel = () => { }
const h5Msg = (type, data) => {
  if (cancel)
    cancel()
  return xhr.request({
    url: `/sys/wechat/h5Msg`,
    method: 'post',
    data,
    cancelToken: new CancelToken((_c) => {
      cancel = () => {
        _c();
        cancel = null;
      }
    })
  })
}

const wait = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, timing)
  })
}

const getContent = (res) => {
  // debugger
  try {
    return JSON.stringify(res.data.content)
  } catch (error) {

  }
}


const getTimestr = () => String(Date.now())

let retryTime = 3

let interval;
let timing = 1000

const reset = async () => {
  try {
    timing = 1000;
    interval && (clearInterval(interval), interval = null);
  } catch (error) {
    console.error(error);
  }
}

const requestLocation = async () => {
  const TIME_STR = getTimestr();

  const reReceive = () => {
    return new Promise((resolve, reject) => {
      interval = setInterval(() => {
        let res = h5Msg(TYPE.RECEIVE)
        const content = getContent(res);
        if (content.requestTimeStr !== TIME_STR) {
          reSend();
        } else {
          reset();
          resolve(content)
        }
      }, timing)
    })
  }

  try {
    await h5Msg(TYPE.SEND, {
      message: MESSAGE.REQ_LOCATION,
      requestTimeStr: TIME_STR
    })
    timing += (Date.now() + Number(TIME_STR) + 200);
    await wait();
    let res = h5Msg(TYPE.RECEIVE)
    let content = getContent(res);
    if (content.requestTimeStr !== TIME_STR) {
      content = await reReceive();
    }
    if (content.message === MESSAGE.RES_LOCATION) {
      await h5Msg(TYPE.SEND, {
        message: MESSAGE.RESET,
        responseTimeStr: content.responseTimeStr,
        requestTimeStr: TIME_STR
      })
      return content.lngLat;
    }
  } catch (error) {
    while (retryTime--) {
      await requestLocation()
      retryTime = 3;
      break;
    }
  } finally {
    reset();
  }
}

const responseLocation = async (getLocation) => {

  const polling = async () => {
    return new Promise((resolve, reject) => {
      interval = setInterval(async () => {
        try {
          let res = await h5Msg(TYPE.RECEIVE);
          let content = getContent(res)
          if (content.message === MESSAGE.REQ_LOCATION || content.message === MESSAGE.RESET) {
            resolve(content)
          }
        } catch (error) {
          reject (error)
        }

      }, timing)
    })
  }

  try {
    let content = await polling()
    const TIME_STR = getTimestr();
    let lngLat = {}
    if (content.message === MESSAGE.REQ_LOCATION) {
      const requestTimeStr = content.requestTimeStr;
      await h5Msg(TYPE.SEND, {
        requestTimeStr,
        message: MESSAGE.RES_LOCATION,
        responseTimeStr: TIME_STR,
        lngLat,
      })
      timing += (Date.now() + Number(TIME_STR) + 200);
    }
    if (content.message === MESSAGE.RESET && content.responseTimeStr === TIME_STR)
      reset()
    responseLocation()

  } catch (error) {
    console.error(error);
    if (!retryTime) {
      $toast({
        title: '错误',
        text: '获取地图定位失败，请重新进入页面',
        during: 2000,
        isShowButton: false
      })
    }
    while (!!retryTime--) {
      await responseLocation()
      retryTime = 3;
      break;
    }

  }
}

export {
  requestLocation,
  responseLocation
}